package gcontent.filter.string;

import java.util.Vector;

import org.apache.log4j.Logger;

import gcontent.entities.Content;
import gcontent.filter.Filter;
import gcontent.filter.error.FilterEx;
import gcontent.utils.StringUtils;

public class FilterString extends Filter {
	
	protected Vector<StringValue> strings = new Vector<StringValue>();
	protected int[] strings_count = null;
	
	protected int min_percentage = 50;
	protected int max_percentage = 100;
	
	private static Logger log = Logger.getLogger(FilterString.class);
		
	private boolean byteEquals(byte[] dest, byte[] orig, int pos)
	{
		for(int i = 0; i < orig.length; i++) {
			if(dest[pos] != orig[i])
				return false;
			
			pos++;
		}
		
		return true;
	}
		
	public void setStrings(Vector<StringValue> strings)
	{
		this.strings = strings;
		this.strings_count = new int[strings.size()];
	}

	public void setInput(String input) throws FilterEx
	{
		FilterStringParams.getParams(input, this);
	}
	
	public int check(Content content)
	{
		byte[] body;
		int n_strings, percentage;
		
		if(this.strings.size() == 0)
			return STATUS_FAILED;
		
		for(int i = 0; i < this.strings.size(); i++)
			this.strings_count[i] = 0;
		
		body = content.getBody();	
		for(int i = 0; i < body.length; i++) {
			/* check each word */
			for(int o = 0; o < this.strings.size(); o++) {
				StringValue str_value = this.strings.get(o);
				int type_search = str_value.getTypeSearch();
				
				byte[] str_b = str_value.getValue().getBytes();
				if((i + str_b.length) <= body.length &&	
					byteEquals(body, str_b, i)) {
					
					switch(type_search) {
						case StringValue.WORD_CONTAINS:
							
							/* word contains */
							log.debug("word contains (" + new String(str_b) + ") found it");
							this.strings_count[o]++;	
							break;
							
						case StringValue.WORD_BEGINS:
							
							/* word begins */
							if(i == 0 || StringUtils.isCharSeparator((char)body[i - 1])) {
									log.debug("word begins (" + new String(str_b) + ") found it");
									this.strings_count[o]++;
							}
							
							break;
							
						case StringValue.WORD_ENDS:
							
							/* word ends */
							if((i == 0 || !StringUtils.isCharSeparator((char)body[i - 1])) && 
								((i + str_b.length + 1) > body.length || StringUtils.isCharSeparator((char)body[i + str_b.length])) ) {
							
								log.debug("word ends (" + new String(str_b) + ") found it");
								this.strings_count[o]++;
							}
							
							break;
							
						case StringValue.WORD_EQUAL:														
							
							/* begin body? */
							if(i == 0) {
								if((str_b.length + 1) > body.length || StringUtils.isCharSeparator((char)body[str_b.length])) {
									log.debug("word equals (" + new String(str_b) + ") found it");
									this.strings_count[o]++;						
								}						
								/* middle body */
							} else if(StringUtils.isCharSeparator((char)body[i - 1]) && 
									((i + str_b.length + 1) > body.length || StringUtils.isCharSeparator((char)body[i + str_b.length]))) {
									log.debug("word equals (" + new String(str_b) + ") found it");
									this.strings_count[o]++;
							}
							
							break;
							
						case StringValue.STRING_CONTAINS:
							
							/* string found */
							this.strings_count[o]++;
							break;
					}										
					
				}
				
			}			
		}
		
		n_strings = 0;
		for(int o = 0; o < this.strings_count.length; o++) {
			if(this.strings_count[o] > 0)
				n_strings++;
		}
		
		percentage = (n_strings * 100) / this.strings_count.length;
		if(percentage >= this.min_percentage && percentage <= this.max_percentage)
			return (STATUS_OK | this.success);

		return (STATUS_FAILED | this.fail);
	}
	
	/* dynamic properties */
	public void set_minpercentage(int min_percentage)
	{
		this.min_percentage = min_percentage;
	}
	
	public void set_maxpercentage(int max_percentage)
	{
		this.max_percentage = max_percentage;
	}
}
